#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>        // close()
#include <arpa/inet.h>     // inet_ntoa()
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <errno.h>

#define PORT 8080
#define BUFFER_SIZE 1024
#define MAX_CLIENTS 1024

int main(){
    int clients_fds[MAX_CLIENTS]={0};
    //将存储描述符的数组中每一个元素设置为0
    for(int i = 0; i < MAX_CLIENTS; i++){
        clients_fds[i] = 0;
    }
    //1. 创建socket
    int server_fd = socket(AF_INET, SOCK_STREAM,0);
    if(server_fd<0){
        perror("socket");
        exit(1);
    }

    //2. 绑定socket
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    int res = bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(res < 0){
        perror("bind failed");
        exit(1);
    }

    //3. 监听
    res = listen(server_fd, 20);
    if(res < 0){
        perror("listen failed");
        exit(1);
    }

    fd_set read_fds;
    while(1){
        //清理集合
        FD_ZERO(&read_fds);
        //将server_fd放入读集合中，监听新连接到来的事件，
        FD_SET(server_fd, &read_fds);
        int max_sd = server_fd;
        //此处遍历数组，将已经建立好的连接socket放入读集合中
        for(int i = 0; i < MAX_CLIENTS; i++){
            //如果描述符大于0则放入读集合中
            if(clients_fds[i] > 0){
                FD_SET(clients_fds[i], &read_fds);
            }
            //更新最大描述符
            if(clients_fds[i] > max_sd){
                max_sd = clients_fds[i];
            }
        }

        //4. 阻塞等待事件发生
        int activity = select(max_sd + 1, &read_fds, NULL, NULL, NULL);
        if((activity < 0) && (errno != EINTR)){
            perror("select");
            exit(1);
        }
       
        //5. 判断server_fd是否在读集合中
        if(FD_ISSET(server_fd, &read_fds)){
            struct sockaddr_in client_addr;
            socklen_t len = sizeof(client_addr);
            int new_socket = accept(server_fd, (struct sockaddr *)&client_addr, &len);
            if(new_socket < 0){
                perror("accept");
            }else{
                for(int i = 0; i < MAX_CLIENTS; i++){
                    if(clients_fds[i] == 0){
                        clients_fds[i] = new_socket;
                        break;
                    }
                }
            }
        }


        //6. 遍历clients_fds数组，判断是否有客户端发来数据
        for(int i = 0; i < MAX_CLIENTS; i++){
            if(clients_fds[i] == 0){
                continue;
            }
            if(FD_ISSET(clients_fds[i], &read_fds)){
                char buffer[BUFFER_SIZE];
                memset(buffer, '\0', BUFFER_SIZE);
                int bytes_received = read(clients_fds[i], buffer, BUFFER_SIZE-1);
                if(bytes_received == 0){
                    //客户端断开连接
                    close(clients_fds[i]);
                    clients_fds[i] = 0;
                    printf("客户端断开连接\n");
                    continue;
                }

                printf("Received: %s\n", buffer);
              
            }
        }
    }
    close(server_fd);
}